package main

import (
	"encoding/json"
	"fmt"
	"github.com/gorilla/websocket"
	"net/http"
)

type connection struct {
	ws   *websocket.Conn
	sc   chan []byte // 信息传输的管道
	data *Data       // 传输的信息
}

// 实现ws的读和写
// ws写数据
func (c *connection) writer() {
	// 遍历管道，取出消息
	for message := range c.sc {
		// 通过websocket将信息发送出去
		c.ws.WriteMessage(websocket.TextMessage, message) // websocket.TextMessage表示utf8格式
	}
	c.ws.Close()
}

// ws读数据
var user_list = []string{} // 用户列表是全局的，所有连接看到的都是同一个用户列表
func (c *connection) reader() {
	// 不断循环的读数据
	for {
		_, message, err := c.ws.ReadMessage() // 调用api读数据
		if err != nil {
			// 没人发送管道是堵塞而不是报错，这里报错表明连接出问题，直接将该连接放入删除管道
			h.r <- c
			break
		}
		// 读取数据
		json.Unmarshal(message, &c.data)
		switch c.data.Type {
		// 登录状态
		case "login":
			c.data.User = c.data.Content // 是登录请求，那么这次传的的内容就是用户名
			c.data.From = c.data.Content
			// 登陆后，将当前用户加入到全局在线用户列表
			user_list = append(user_list, c.data.User)
			// 更新连接内的用户列表
			c.data.UserList = user_list
			// 将读到的数据存到连接器
			data_b, _ := json.Marshal(c.data)
			h.b <- data_b
		// 普通状态
		case "user":
			c.data.Type = "user"
			data_b, _ := json.Marshal(c.data)
			h.b <- data_b
		// 注销状态
		case "logout":
			c.data.Type = "logout"
			user_list = del(user_list, c.data.User) // 从全局用户列表删除当前用户
			data_b, _ := json.Marshal(c.data)
			c.data.UserList = user_list
			c.data.Content = c.data.User
			h.b <- data_b
			h.r <- c
		default:
			fmt.Print("========default================")
		}
	}
}

// 删除用户切片中的数据
func del(slice []string, user string) []string {
	// 判断各种情况
	count := len(slice)
	if count == 0 {
		return slice
	}
	if count == 1 && slice[0] == user {
		return []string{}
	}
	var n_slice = []string{}
	// 切片没有del方法，只能利用索引，把需要的部分重新赋值给新的切片
	for i := range slice {
		if slice[i] == user && i == count {
			return slice[:count]
		} else if slice[i] == user {
			n_slice = append(slice[:i], slice[i+1:]...)
			break
		}
	}
	fmt.Println(n_slice)
	return n_slice
}

// 定义升级器，将http请求升级为websocket请求
var wu = &websocket.Upgrader{ReadBufferSize: 512, WriteBufferSize: 512,
	CheckOrigin: func(r *http.Request) bool {
		return true
	}} //CheckOrigin表示能否跨域

// ws的回调函数
func myws(w http.ResponseWriter, r *http.Request) {
	ws, err := wu.Upgrade(w, r, nil) // 将http连接升级为websocket
	if err != nil {
		return
	}
	// 初始化connection连接对象
	c := &connection{sc: make(chan []byte, 256), ws: ws, data: &Data{}}
	h.u <- c
	// ws读写数据
	go c.writer()
	c.reader()
	// 回调函数执行完毕就是浏览器退出，就执行用户退出
	defer func() {
		c.data.Type = "logout"
		user_list = del(user_list, c.data.User)
		c.data.UserList = user_list
		c.data.Content = c.data.User
		data_b, _ := json.Marshal(c.data)
		h.b <- data_b
		h.r <- c
	}()
}
